library ieee;
use ieee.std_logic_1164.all;

entity mux4to1 is
	port (I0, I1, I2, I3 : in bit ; 
		S0, S1 : in bit;
        F : out bit);
end entity mux4to1;

architecture DATAFLOW of mux4to1 is
    
    component Decoder2x4
		port (
			a,b : in bit;
			z1, z2, z3, z4 : out bit
		);
	end component;
	
	for all : Decoder2x4 use entity work.Decoder2x4(DATAFLOW);
	
	signal decode_out : bit_vector(3 downto 0);
	signal and_out : bit_vector(3 downto 0);
	signal or_out : bit;
	
	begin
		decoder : Decoder2x4 port map (S0, S1, decode_out(0), decode_out(1), decode_out(2), decode_out(3));
    	and_out(0) <= I0 and decode_out(0);
    	and_out(1) <= I1 and decode_out(1);
    	and_out(2) <= I2 and decode_out(2);
    	and_out(3) <= I3 and decode_out(3);
		or_out <= and_out(0) or and_out(1) or and_out(2) or and_out(3);
		F <= or_out;
    
end architecture DATAFLOW;

architecture STRUCTURAL of mux4to1 is

	component Decoder2x4
		port (
		a,b : in bit;
		z1, z2, z3, z4 : out bit
	);
	end component;
	component and2
		port (
		a,b : in bit;
		z : out bit
	);
	end component;
	component or3
		port (
		a,b,c : in bit;
		z : out bit
	);
	end component;
	component or2
		port (
		a,b : in bit;
		z : out bit
	);
	end component;
	
	for all : Decoder2x4 use entity work.Decoder2x4(STRUCTURAL);
	for all : and2 use entity work.and2(DATAFLOW);
	for all : or3 use entity work.or3(DATAFLOW);
	for all : or2 use entity work.or2(DATAFLOW);
	
	signal decode_out : bit_vector(3 downto 0);
	signal and_out : bit_vector(3 downto 0);
	signal or3_out : bit;
	
begin

  decoder : Decoder2x4 port map (S0, S1, decode_out(0), decode_out(1), decode_out(2), decode_out(3));
  and_0 : and2 port map (I0, decode_out(0), and_out(0));
  and_1 : and2 port map (I1, decode_out(1), and_out(1));
  and_2 : and2 port map (I2, decode_out(2), and_out(2));
  and_3 : and2 port map (I3, decode_out(3), and_out(3));
  or_3 : or3 port map (and_out(0), and_out(1), and_out(2), or3_out);
  or_2 : or2 port map (or3_out, and_out(3), F);

end architecture STRUCTURAL;
